#!/usr/bin/env python
# coding=UTF-8
import logging
import time
import datetime
from hashlib import md5
import urllib, urllib2
import random, json

import redisco
from redisco.containers import List, Hash
from nsq.http import nsqd

import config
import dao
import game
import paohuzi
import ddz
import douniu
import sangong
import guozha
import pincidao
import gandengyan
import ygmj

from pygeohash import geohash, geohash_haversine_distance
import itertools
import threading


#_lock = threading.Lock()

redisco.connection_setup(host=config.REDIS_HOST, port=config.REDIS_PORT, db=config.REDIS_DB)

def nsq_pub(topic, message):
    try:
        nsq_client = nsqd.Client("http://%s/" % config.NSQ_HTTP)
        if isinstance(message, dict):
            message = json_encode(message)
        logging.info(u"推送消息:%s" % message)
        nsq_client.pub(topic, message)
        return True
    except:
        logging.error("nsq send error", exc_info=True)
        return False
    
def json_encode(data):
    return json.dumps(data, separators=(',', ':'))

def push_room_cast(topic, rid, bid, uid, data):
    l = List("r:%s:p" % rid)
    for member in l.members:
        if member:
            nsq_pub("response", json_encode({"d":data, "u":str(member), "b":bid, "t":topic}))
    return 

def push_member_cast(topic, members, bid, uid, data):
    for member in members:
        if not member or member == str(uid):
            continue
        nsq_pub("response", json_encode({"d":data, "u":str(member), "b":bid, "t":topic}))
    return

def push_uid_msg(reader, bid, uid, data):
    nsq_pub("response", json_encode({"d":data, "u":str(uid), "b":bid, "t":reader._topic}))
    return

def online(reader, bid, uid, data):
    user_info = Hash("%s_%s" % (bid, uid))
    user_info['online'] = 'y'
    rid = user_info['rid']
    if not rid:
        rid = data.get("rid")
    if rid:
        l = List("r:%s:p" % rid)
        data = {"act":"online", "uid":uid, "rid":rid}
        push_member_cast("status", l.members, bid, uid, data)
        db = dao.Game_DB()
        online = 'y'
        db.update_player_online(rid, uid, online)
        room = Hash("r:%s" % rid)
        cid = room['cid']
        if cid:
            db.update_club_online(uid, online)
        mid = room['mid']
        if mid:
            db.update_match_online(mid, uid, online)
        
        room_info = db.get_room(rid, bid)
        game_round = room_info['game_round']
        if not game_round:
            game_round = 1
        else:
            game_round = int(game_round)
        game_type = room['game_type']
        #if game_round <= 1:
        #    renotify_join_room(bid, rid, uid)
        room = Hash("r:%s" % rid)
        #ready_src = data.get('src', 1)
        #if room['status'] == 'over' and not ready_src:
        #    game_over_msg = db.get_game_over_msg(rid, game_round, 'game_over', uid)
        #    if game_over_msg:
        #        game.nsq_pub(urllib.unquote(game_over_msg['msg']))
        if room_info['flag'] != 'y':
            renotify_join_room(bid, rid, uid, "from_mysql")
            #game_over_msg = db.get_game_over_msg(rid, game_round, 'game_over', uid)
            #if game_over_msg:
            #    game.nsq_pub(urllib.unquote(game_over_msg['msg']))
            mid = room_info['mid']
            if mid:
                match_info = db.match_info(bid, mid)
                member_info = db.match_member_info(mid, uid)
                if match_info['status'] == 3:
                    msg = u"比赛结束~ 排名:%s" % member_info['ranking']
                    message = {"b":bid, "u":uid, "t":"game", "d":{"act":"match_over", "mid":mid, "msg":msg, "rid":rid}}
                    game.nsq_pub(message)
                else: 
                    mround = match_info['mround']
                    if member_info['res'] in (0, 2):
                        msg = u"很遗憾,您被淘汰"
                        message = {"b":bid, "u":uid, "t":"game", "d":{"act":"match_out", "mid":mid, "msg":msg, "ranking":member_info['ranking'], "rid":rid}}
                        game.nsq_pub(message)
                    else:
                        try:
                            next_room = db.get_joined_match_room(mid, uid)
                            if next_room:
                                msg = u"恭喜你晋级,可以进入下一轮"
                                message = {"b":bid, "u":str(uid), "t":"game", "d":{"act":"match_in", "mid":mid, "msg":msg, "rid":rid, "next_rid":next_room['rid']}}
                                game.nsq_pub(message)
                        except:
                            logging.error(u"errr", exc_info=True)
        if room['status'] == 'start':
            if game_type == 'ldfpf':
                paohuzi.get_last_data(reader, bid, uid, data)
            elif game_type == 'ddz':
                ddz.get_last_data(reader, bid, uid, data)
            elif game_type == 'dn':
                douniu.get_last_data(reader, bid, uid, data)
            elif game_type == 'sg':
                sangong.get_last_data(reader, bid, uid, data)
            elif game_type == 'gz':
                guozha.get_last_data(reader, bid, uid, data)
            elif game_type == 'pcd':
                pincidao.get_last_data(reader, bid, uid, data)
            elif game_type == 'gdy':
                gandengyan.get_last_data(reader, bid, uid, data)
            elif game_type =='ygmj':
                ygmj.get_last_data(bid, uid, rid)
            else:
                game.get_last_data(reader, bid, uid, data)
        
        room_info = db.get_room(rid, bid)
        apply_user = room_info['apply_user']
        if room_info['dismiss_apply'] and room_info['flag'] == 'y' and str(uid) != apply_user:
            if str(uid) not in room_info['agree_user'].split(","):
                timer = int(room_info['dismiss_apply'][14:16]) - int(time.strftime("%M"))
                game.nsq_pub({"b":bid, "u":uid, "t":"game", "d":{"act":"dismiss_apply", "uid":apply_user, "timer":timer, "rid":rid}})
        

def offline(reader, bid, uid, data):
    user_info = Hash("%s_%s" % (bid, uid))
    user_info['online'] = 'n'
    rid = user_info['rid']
    if not rid:
        rid = data.get("rid")
    if rid:
        l = List("r:%s:p" % rid)
        data = {"act":"offline", "uid":uid, "rid":rid}
        push_member_cast("status", l.members, bid, uid, data)
        db = dao.Game_DB()
        online = 'n'
        db.update_player_online(rid, uid, online)
        room = Hash("r:%s" % rid)
        cid = room['cid']
        if cid:
            db.update_club_online(uid, online)
        mid = room['mid']
        if mid:
            db.update_match_online(mid, uid, online)
            if room['game_type'] == 'pdk':
                tdh = game.PaoDeKuai(rid, bid)
                if room['stop_pop_user'] == str(uid):
                    tdh.auto_put(str(uid))
                return
            if room['game_type'] == 'zzmj':
                tdh = game.ZZMaJiang(rid, bid)
            elif room['game_type'] == 'hzmj':
                tdh = game.HZMaJiang(rid, bid)
            elif room['game_type'] == 'csmj':
                tdh = game.CSMaJiang(rid, bid)
            else:
                tdh = game.MaJiang(rid, bid)
            if room['stop_pop_user']:
                if room['stop_pop_user'] == str(uid):
                    tdh.pass_card(uid, {})
                    logging.error(u"用户离线自动pass:%s" % uid)
            if room['last_get_user'] == str(uid) and room['status'] == 'start':
                logging.error(u"用户离线自动出牌:%s" % uid)
                p = game.Player(uid, bid, rid)
                card = p.current_card.members[-1]
                tdh.put_card(uid, {"card":card})
                

def im_chat(reader, bid, uid, data):
    user_info = Hash("%s_%s" % (bid, uid))
    rid = user_info['rid']
    if rid:
        data['uid'] = uid
        data['rid'] = rid
        push_room_cast("im", rid, bid, uid, data)
    return

def create_room(reader, bid, uid, data):
    logging.info("create room data======================:%s"%data)
    rid = data['rid']
    #l = List("r:%s:p" % rid)
    #l.append(uid)
    #for i in range(int(data['player']) - 1):
    #    l.append('')
    user_info = Hash("%s_%s" % (bid, uid))
    user_info.hset("rid", rid)
    room = Hash("r:%s" % rid)
    admin = data.get("admin")
    logging.info('create room data===============',data)
    if not admin:
        admin = uid
    gid = data.get("gid", "")
    mid = data.get("mid", "")
    cid = data.get("cid", "")
    must_put = data.get("must_put", "y")
    black_three_first = data.get("black_three_first", "n")
    card_warning = data.get("card_warning", "1")
    end_huxi = data.get("end_huxi", "200")
    max_bomb = data.get("max_bomb", 5)
    #跑得快牌数量
    card_num = data.get("card_num", 16)
    
    #上庄模式
    dealer_mode = data.get("dealer_mode", '')
    #过炸几副牌
    card_pack = data.get("card_pack", '')
    #过炸加王
    add_joker = data.get("add_joker", '')
    #夹子
    jiazi = data.get("jiazi","n")
    #底注
    base = data.get("base", '1')
    #玩法选择
    game_mode = data.get("game_mode", '')
    message = {"game_mode":game_mode,"base":base,"card_pack":card_pack,"jiazi":jiazi,"add_joker":add_joker,"dealer_mode":dealer_mode,"card_num":card_num,"max_bomb":max_bomb, "end_huxi":end_huxi, "must_put":must_put, "black_three_first":black_three_first, "card_warning":card_warning, "mid":mid, "gid":gid, "cid":cid, "status":"", "admin":admin, "dealer":uid, "bid":bid, "last_get_user":uid, "game_round":1, "all_round":data['all_round'], "card":data['card'], "game_type":data['game_type'], "horse":data['horse'], "grab_bar_win":data['grab_bar_win'], "grab_bar_duty":data['grab_bar_duty'], "bar_win_duty":data['bar_win_duty'], "seven_pair_win":data['seven_pair_win']}
    #logging.info(message)
    room.update(message)

def cal_distance(lat1, lon1, lat2, lon2):
    if not (lat1 and lon1 and lat2 and lon2):
        return u"未知"
    elif lat1 == '0' or lon1 =='0' or lat2 == '0' or lon2 == '0':
        return u"未知"
    a = geohash.encode(float(lat1), float(lon1))
    b = geohash.encode(float(lat2), float(lon2))
    distance = int(geohash_haversine_distance(a, b))
    if distance > 1000:
        distance = u"%.2f公里" % (distance/1000.0)
    else:
        distance = u"%s米" % distance
    return distance

def join_room(reader, bid, uid, data):
    seat = int(data['seat'])
    rid = data['rid']
    l = List("r:%s:p" % rid)
    members = l.members
    if not members:
        return
    l[seat - 1] = uid
    user_info = Hash("%s_%s" % (bid, uid))
    user_info.hset("rid", rid)
    location_list = data.get("location_list", [])
    data['online'] = 'y'
    for member in members:
        if member == str(uid) or not member:
            continue
        location_info = u""
        p = Hash("%s_%s" % (bid, member))
        for loc in location_list:
            pname = p['name']
            #if len(pname) > 6:
            #    pname = p['name'][:6]
            if pname not in loc.encode("utf-8"):
                location_info += loc
        #logging.info(location_info)
        data['location_info'] = location_info
        game.nsq_pub({"b":bid, "u":member, "t":"game", "d":data})
    #push_member_cast("game", members, bid, uid, data)
    return

def renotify_join_room(bid, rid, ready_uid, data_from=""):
    '''start之前通知所有玩家重新进入'''
    db = dao.Game_DB()
    members = []
    room_players = db.query_room_players(rid, bid)
    for player in room_players:
        members.append(str(player['uid']))
    
    location_info = u""
    for (p1, p2) in itertools.combinations(room_players, 2):
        if str(p1['uid'])!= ready_uid and str(p2['uid']) != ready_uid:
            distance = cal_distance(p1['gps_lat'], p1['gps_lon'], p2['gps_lat'], p2['gps_lon'])
            text = u"%s与%s距离:%s\n" % (p1['name'], p2['name'], distance)
            location_info += text

    for uid in members:
        if not uid or uid == ready_uid:
            continue
        row = db.get_player(rid, uid)
        user_info = db.user_info(bid, uid)
        data = {"act":"join_room", "rid":rid, "location_info":location_info, "ranking":0, "name":user_info['name'], "head":user_info['head'],"sex":user_info['sex'], "seat":row['seat'], "uid":uid, "ip":row['ip'], "status":row['status'], "online":row['online'], "score":row['score'], "gps_lat":row['gps_lat'], "gps_lon":row['gps_lon']}
        game.nsq_pub({"b":bid, "u":ready_uid, "t":"game", "d":data})
        #for member in members:
        #    if member == uid:
        #        continue
        #    game.nsq_pub({"b":bid, "u":member, "t":"game", "d":data})

def ready(reader, bid, uid, data):
    user_info = Hash("%s_%s" % (bid, uid))
    if data.get("offline"):
        user_info['online'] = 'n'
    else:
        if not data.get("auto_ready"):
            user_info['online'] = 'y'
    rid = str(data.get("rid", ""))
    if not rid:
        rid = user_info['rid']
        if not rid:
            logging.error(u"用户对应rid不存在:%s" % uid)
            return
    else:
        if not isinstance(rid, str):
            rid = str(int(rid))
        user_info['rid'] = rid
        
    data['uid'] = uid
    l = List("r:%s:p" % rid)
    members = l.members
    data['act'] = 'ready'
    data['rid'] = rid
    push_room_cast("game", rid, bid, uid, data)
    #global _lock
    #_lock.acquire()
    db = dao.Game_DB()
    db.update_player_ready(rid, uid)
    db.commit()
    room_player_cnt = db.room_player_cnt(rid, 1)
    #_lock.release()
    room_info = db.get_room(rid, bid)
    if not room_info:
        logging.error(u"===房间不存在:%s" % rid)
        return
    game_round = room_info['game_round']
    if not game_round:
        game_round = 1
    else:
        game_round = int(game_round)
    game_type = room_info['game_type']
    #if not data.get('src') and game_round <= 1 and room_info['flag'] == 'y':
    #    renotify_join_room(bid, rid, uid)
    room = Hash("r:%s" % rid)
    if room_player_cnt['player'] == len(members):
        if room['status'] != 'start' and room_info['flag'] == 'y' and game_round < room_info['all_round']:
            # 开始游戏
            logging.info(u"玩家全部准备:%s,开始游戏" % rid)
            dealer = room.get("dealer")
            if not dealer:
                dealer = members[0]
            match_id = room['mid']
            if match_id:
                if not game_round:
                    game_round = 1
                idx = (int(game_round) - 1) % len(members)
                dealer = members[idx]
            
            nsq_pub("game_start", {"b":bid, "u":"", "t":"game", "d":{"act":"game_start", "rid":rid, "dealer":dealer, "game_type":game_type}})

def quit_room(reader, bid, uid, data):
    rid = data['rid']
    l = List("r:%s:p" % rid)
    members = l.members
    if uid in members:
        idx = members.index(uid)
        l[idx] = ''
    push_member_cast("game", members, bid, uid, data)
    return

def dismiss_room(reader, bid, uid, data):
    rid = data['rid']
    room = Hash("r:%s" % rid)
    l = List("r:%s:p" % rid)
    data['rid'] = rid
    db = dao.Game_DB()
    members = l.members
    if not members:
        rows = db.query_room_players(rid, bid)
        members = [str(row['uid']) for row in rows]
    for member in members:
        if member:
            game.nsq_pub({"b":bid, "u":str(member), "t":"game", "d":data})
    game_type = room['game_type']
    if game_type == 'zzmj':
        tdh = game.ZZMaJiang(rid, bid)
    elif game_type == 'hzmj':
        tdh = game.HZMaJiang(rid, bid)
    elif game_type == 'csmj':
        tdh = game.CSMaJiang(rid, bid)
    elif game_type == 'pdk':
        tdh = game.PaoDeKuai(rid, bid)
    elif game_type == 'ldfpf':
        tdh = paohuzi.PaoHuZi(rid, bid)
    elif game_type == 'ddz':
        tdh = ddz.DouDiZhu(rid, bid)
    elif game_type == 'gz':
        tdh = guozha.GuoZha(rid, bid)
    elif game_type == 'pcd':
        tdh = pincidao.PinCiDao(rid, bid)
    elif game_type == 'dn':
        tdh = douniu.DouNiu(rid, bid)
    elif game_type == 'sg':
        tdh = sangong.SanGong(rid, bid)
    elif game_type == 'gdy':
        tdh = gandengyan.GanDengYan(rid, bid)
    elif game_type == 'ygmj':
        tdh = ygmj.YgMajiang(rid,bid)
    else:
        tdh = game.MaJiang(rid, bid)
    
    room_info = db.get_room(rid, bid)
    if room_info['flag'] == 'y':
        db.dismiss_room(rid)
    l.clear()
    try:
        logging.info(u"==============%s,%s" % (game_type, rid))
        tdh.dismiss()
        room.clear()
    except:
        logging.error(u"解散房间异常", exc_info=True)

def dismiss_apply(reader, bid, uid, data):
    user_info = Hash("%s_%s" % (bid, uid))
    rid = data.get("rid")
    if not rid:
        rid = user_info['rid']
    
    l = List("r:%s:p" % rid)
    members = l.members
    data['uid'] = uid
    data['timer'] = 5
    db = dao.Game_DB()
    room_info = db.get_room(rid, bid)
    if room_info['mid']:
        logging.error(u"比赛的房间不可解散:%s,%s,%s" % (bid, uid, rid))
        return
    #push_room_cast("game", rid, bid, uid, data)
    data['rid'] = rid
    for member in members:
        game.nsq_pub({"b":bid, "u":str(member), "t":"game", "d":data})
    if not room_info['dismiss_apply']:
        dismiss_apply_time = (datetime.datetime.now() + datetime.timedelta(minutes=5)).strftime("%Y-%m-%d %H:%M:%S")
        db.dismiss_apply(rid, dismiss_apply_time, uid)
    return

def dismiss_agree(reader, bid, uid, data):
    user_info = Hash("%s_%s" % (bid, uid))
    rid = user_info['rid']
    db = dao.Game_DB()
    l = List("r:%s:p" % rid)
    members = l.members
    data['uid'] = uid
    data['rid'] = rid
    #push_room_cast("game", rid, bid, uid, data)
    for member in members:
        game.nsq_pub({"b":bid, "u":str(member), "t":"game", "d":data})
    db.dismiss_agree(rid, uid)
    db.commit()
    room_info = db.get_room(rid, bid)
    logging.info(room_info)
    if room_info['flag'] != 'y':
        return
    if not room_info['dismiss_apply']:
        return
    agree_num = room_info['dismiss_agree']
    #agree_user = room_info['agree_user']
    #agree_num = len(set(agree_user.split(",")))
    player_num = room_info['player']
    if player_num <= (agree_num + 2):
        i = db.dismiss_room(rid)
        for member in members:
            game.nsq_pub({"b":bid, "u":member, "t":"game", "d":{"rid":rid, "act":"dismiss_res", "msg":u"玩家同意解散房间"}})
        if room_info['game_type'] == 'zzmj':
            tdh = game.ZZMaJiang(rid, bid)
        elif room_info['game_type'] == 'hzmj':
            tdh = game.HZMaJiang(rid, bid)
        elif room_info['game_type'] == 'csmj':
            tdh = game.CSMaJiang(rid, bid)
        elif room_info['game_type'] == 'pdk':
            tdh = game.PaoDeKuai(rid, bid)
            tdh.game_over('', True, '')
            room_info = db.get_room(rid, bid)
            if room_info['all_round'] > room_info['game_round']:
                tdh.dismiss()
            return
        elif room_info['game_type'] == 'ldfpf':
            tdh = paohuzi.PaoHuZi(rid, bid)
            tdh.game_over('','','','', 0, True)
            #tdh.dismiss()
            return
        elif room_info['game_type'] == 'ddz':
            tdh = ddz.DouDiZhu(rid, bid)
            tdh.game_over('', True, '')
            room_info = db.get_room(rid, bid)
            if room_info['all_round'] > room_info['game_round']:
                tdh.dismiss()
            return
        elif room_info['game_type'] == 'gz':
            tdh = guozha.GuoZha(rid, bid)
            tdh.game_over(from_dissmiss=True)
            return
        elif room_info['game_type'] == 'pcd':
            tdh = pincidao.PinCiDao(rid, bid)
            tdh.game_over(from_dissmiss=True)
            return
        elif room_info['game_type'] == 'dn':
            tdh = douniu.DouNiu(rid, bid)
            tdh.game_over(from_dissmiss=True)
            return
        elif room_info['game_type'] == 'sg':
            tdh = sangong.SanGong(rid, bid)
            tdh.game_over(from_dissmiss=True)
            return
        elif room_info['game_type'] == 'gdy':
            tdh = gandengyan.GanDengYan(rid, bid)
            tdh.game_over(from_dissmiss=True)
            return
        else:
            tdh = game.MaJiang(rid, bid)
            
        tdh.game_over(from_dissmiss=True)
        room_info = db.get_room(rid, bid)
        if room_info['all_round'] > room_info['game_round']:
            tdh.dismiss()
        return

def dismiss_refuse(reader, bid, uid, data):
    user_info = Hash("%s_%s" % (bid, uid))
    rid = user_info['rid']
    l = List("r:%s:p" % rid)
    members = l.members
    data['uid'] = uid
    data['rid'] = rid
    #push_room_cast("game", rid, bid, uid, data)
    player_stat = []
    for member in members[1:]:
        player_stat.append({})
    for member in members:
        game.nsq_pub({"b":bid, "u":member, "t":"game", "d":data})
    db = dao.Game_DB()
    db.dismiss_refuse(rid)
    for member in members:
        game.nsq_pub({"b":bid, "u":member, "t":"game", "d":{"act":"dismiss_res", "msg":u"有玩家拒绝解散,游戏继续", "rid":rid}})
    
    
def game_act(reader, bid, uid, data):
    user_info = Hash("%s_%s" % (bid, uid))
    rid = user_info['rid']
    if not rid:
        rid = data.get("rid", "")
    room = Hash("r:%s" % rid)
    game_type = room['game_type']
    logging.info('gametype-------------------:%s,rid==:%s,room:%s'%(game_type,rid,room))
    if game_type == 'zzmj':
        tdh = game.ZZMaJiang(rid, bid)
    elif game_type == 'hzmj':
        tdh = game.HZMaJiang(rid, bid)
    elif game_type == 'csmj':
        tdh = game.CSMaJiang(rid, bid)
    elif game_type == 'pdk':
        tdh = game.PaoDeKuai(rid, bid)
    elif game_type == 'ldfpf':
        tdh = paohuzi.PaoHuZi(rid, bid)
    elif game_type == 'ddz':
        tdh = ddz.DouDiZhu(rid, bid)
    elif game_type == 'dn':
        tdh = douniu.DouNiu(rid, bid)
    elif game_type == 'gz':
        tdh = guozha.GuoZha(rid, bid)
    elif game_type == 'pcd':
        tdh = pincidao.PinCiDao(rid, bid)
    elif game_type == 'sg':
        tdh = sangong.SanGong(rid, bid)
    elif game_type == 'gdy':
        tdh = gandengyan.GanDengYan(rid, bid)
    elif game_type == 'ygmj':
        tdh = ygmj.YgMajiang(rid,bid)
    else:
        tdh = game.MaJiang(rid, bid)
    if data['act'] == 'put_card':
        tdh.put_card(uid, data)
    elif data['act'] == 'pass':
        tdh.pass_card(uid, data)
    elif data['act'] == 'dark_bar':
        tdh.dark_bar(uid, data)
    elif data['act'] == 'pair_bar':
        tdh.pair_bar(uid, data)
    elif data['act'] == 'bar':
        tdh.bar(uid, data)
    elif data['act'] == 'pair':
        tdh.pair(uid, data)
    elif data['act'] == 'pair_bar_win':
        tdh.pair_bar_win(uid, data)
    elif data['act'] == 'win':
        tdh.win(uid, data)
    elif data['act'] == 'put_win':
        tdh.put_win(uid, data)
    elif data['act'] == 'eat':
        tdh.eat(uid, data)
    elif data['act'] == 'cancel_rob':
        tdh.cancel_rob(uid, data)
    elif data['act'] == 'rob_landlord':
        tdh.rob_landlord(uid, data)
    elif data['act'] == 'rob':
        tdh.rob(uid, data)
    elif data['act'] == 'double_select':
        tdh.double_select(uid, data)
    elif data['act'] == 'show_res':
        tdh.show_res(uid, data)
    elif data['act'] == 'game_start':
        rid = data['rid']
        room = Hash("r:%s" % rid)
        dealer = room['dealer']
        game_type = room['game_type']
        if game_type == 'zzmj':
            tdh = game.ZZMaJiang(rid, bid, dealer)
        elif game_type == 'hzmj':
            tdh = game.HZMaJiang(rid, bid, dealer)
        elif game_type == 'csmj':
            tdh = game.CSMaJiang(rid, bid, dealer)
        elif game_type == 'pdk':
            tdh = game.PaoDeKuai(rid, bid, dealer)
        elif game_type == 'ldfpf':
            tdh = paohuzi.PaoHuZi(rid, bid, dealer)
        elif game_type == 'ddz':
            tdh = ddz.DouDiZhu(rid, bid, dealer)
        elif game_type == 'dn':
            tdh = douniu.DouNiu(rid, bid, dealer)
        elif game_type == 'gz':
            tdh = guozha.GuoZha(rid, bid, dealer)
        elif game_type == 'pcd':
            tdh = pincidao.PinCiDao(rid, bid, dealer)
        elif game_type == 'sg':
            tdh = sangong.SanGong(rid, bid, dealer)
        elif game_type == 'gdy':
            tdh = gandengyan.GanDengYan(rid, bid, dealer)
        elif game_type == 'ygmj':
            tdh = ygmj.YgMajiang(rid,bid,dealer);
        else:
            tdh = game.MaJiang(rid, bid, dealer)
        tdh.start()
    return

def job_dismiss_room():
    db = dao.Game_DB()
    room_list = db.expire_room()
    for room in room_list:
        rid = room['rid']
        bid = room['bid']
        db.dismiss_room(rid)
        card = room['card']
        uid = room['admin']
        #db.deduct_card(bid, uid, card)
        if room['game_type'] == 'zzmj':
            tdh = game.ZZMaJiang(rid, bid)
        elif room['game_type'] == 'hzmj':
            tdh = game.HZMaJiang(rid, bid)
        elif room['game_type'] == 'csmj':
            tdh = game.CSMaJiang(rid, bid)
        elif room['game_type'] == 'pdk':
            tdh = game.PaoDeKuai(rid, bid)
        elif room['game_type'] == 'ldfpf':
            tdh = paohuzi.PaoHuZi(rid, bid)
            tdh.game_over(from_dissmiss=True)
            return
        elif room['game_type'] == 'ddz':
            tdh = ddz.DouDiZhu(rid, bid)
        elif room['game_type'] == 'gz':
            tdh = guozha.GuoZha(rid, bid)
        elif room['game_type'] == 'pcd':
            tdh = pincidao.PinCiDao(rid, bid)
        elif room['game_type'] == 'dn':
            tdh = douniu.DouNiu(rid, bid)
        elif room['game_type'] == 'sg':
            tdh = sangong.SanGong(rid, bid)
        elif room['game_type'] == 'gdy':
            tdh = gandengyan.GanDengYan(rid, bid)
        else:
            tdh = game.MaJiang(rid, bid)
        tdh.game_over(from_dissmiss=True)
        room_info = db.get_room(rid, bid)
        if room_info['all_round'] > room_info['game_round']:
            tdh.dismiss()

def start_match(reader, bid, uid, data):
    rid = data['rid']
    db = dao.Game_DB()
    exp_time = (datetime.datetime.now() + datetime.timedelta(seconds=15)).strftime("%Y-%m-%d %H:%M:%S")
    db.add_cron(bid, 'auto_ready', rid, 0, exp_time)
    #l = List("r:%s:p" % rid)
    #members = l.members
    #for uid in members:
    #    user_info = Hash("%s_%s" % (bid, uid))
    #    if user_info['online'] != 'y':
    #        data['offline'] = 'y'
    #        ready(reader, bid, uid, data)

def stop_match(reader, bid, uid, data):
    mid = data['mid']
    db = dao.Game_DB()
    rows = db.query("select * from t_room where mid=%s and flag='y'" % mid)
    for room in rows:
        bid = room['bid']
        rid = room['rid']
        if room['game_type'] == 'zzmj':
            tdh = game.ZZMaJiang(rid, bid)
        elif room['game_type'] == 'hzmj':
            tdh = game.HZMaJiang(rid, bid)
        elif room['game_type'] == 'csmj':
            tdh = game.CSMaJiang(rid, bid)
        elif room['game_type'] == 'pdk':
            tdh = game.PaoDeKuai(rid, bid)
        else:
            tdh = game.MaJiang(rid, bid)
        tdh.game_over(from_dissmiss=True)
        room_info = db.get_room(rid, bid)
        if room_info['all_round'] > room_info['game_round']:
            tdh.dismiss()
        

def client_report(reader, bid, uid, data):
    db = dao.Game_DB()
    ip = data.get('ip')
    if not ip:
        return
    port = data.get('port', 8098)
    client = data.get('total', 0)
    row = db.get_connserver(ip, port)
    if row:
        db.update_connserver(ip, port, client)
    else:
        db.add_connserver(ip, port, client)

def del_game_cron():
    db = dao.Game_DB()
    #db.execute("update t_game set status=3 where status=0 and ctime<now()-interval 8 hour")
    rows = db.query("select * from t_game where status=0 and ctime<now()-interval 8 hour")
    for row in rows:
        db.execute("delete from t_game_member where gid=%s" % row['gid'])
        db.execute("delete from t_game where gid=%s" % row['gid'])
    
def job_cron():
    db = dao.Game_DB()
    rows = db.query("select * from t_cron where exp_time<now()")
    for row in rows:
        bid = row['bid']
        act = row['act']
        rid = row['rid']
        uid = row['uid']
        if act == 'auto_ready':
            if rid:
                l = List("r:%s:p" % rid)
                members = l.members
                for uid in members:
                    ready('', bid, uid, {"rid":rid, "act":"ready", "auto_ready":"y"})
                
                for uid in members:
                    user_info = Hash("%s_%s" % (bid, uid))
                    if user_info['online'] != 'y':
                        offline('', bid, uid, {})
                    
            elif uid:
                ready('', bid, uid, {"rid":rid, "act":"ready", "auto_ready":"y"})
                
            db.execute("delete from t_cron where id=%s" % row['id'])
        logging.info(u"处理超时任务:%s, %s, %s, %s" % (bid, act, rid, uid))

def game_start(reader, bid, uid, data):
    rid = data['rid']
    room = Hash("r:%s" % rid)
    logging.info(u"房间%s牌局开始" % rid)
    if room['status'] == 'start':
        logging.error(u"牌局%s已开始,不能重复发牌" % rid)
        return
    dealer = data['dealer']
    game_type = data['game_type']
    if game_type == 'zzmj':
        tdh = game.ZZMaJiang(rid, bid, dealer)
    elif game_type == 'hzmj':
        tdh = game.HZMaJiang(rid, bid, dealer)
    elif game_type == 'csmj':
        tdh = game.CSMaJiang(rid, bid, dealer)
    elif game_type == 'pdk':
        tdh = game.PaoDeKuai(rid, bid, dealer)
    elif game_type == 'ldfpf':
        tdh = paohuzi.PaoHuZi(rid, bid, dealer)
    elif game_type == 'ddz':
        tdh = ddz.DouDiZhu(rid, bid, dealer)
    elif game_type == 'dn':
        tdh = douniu.DouNiu(rid, bid, dealer)
    elif game_type == 'gz':
        tdh = guozha.GuoZha(rid, bid, dealer)
    elif game_type == 'pcd':
        tdh = pincidao.PinCiDao(rid, bid, dealer)
    elif game_type == 'sg':
        tdh = sangong.SanGong(rid, bid, dealer)
    elif game_type == 'gdy':
        tdh = gandengyan.GanDengYan(rid, bid, dealer)
    elif game_type=="ygmj":
        tdh = ygmj.YgMajiang(rid,bid,dealer)
    else:
        tdh = game.MaJiang(rid, bid, dealer)
    tdh.start()
    
    try:
        game_round = int(room['game_round'])
        if game_round == 1:
            if room['mid']:
                deduct_flag = False
            else:
                deduct_flag = True
                
            if deduct_flag:
                db = dao.Game_DB()
                room_info = db.get_room(rid, bid)
                admin = room_info['admin']
                card = room_info['card']
                db.deduct_card(bid, admin, card)
                nsq_pub({"act":"deduct_card", "bid":bid, "uid":admin, "card":card, "rid":rid}, "total")
                logging.info(u"房间%s开始发牌,扣除房卡, bid:%s,uid:%s,card:%s" % (rid, bid, admin, card))
    except:
        logging.error(u"扣除房卡异常%s" % rid, exc_info=True)
        
        
